/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jacky.lanlan.song.util.builder;

import java.util.Comparator;

/**
 * Assists in implementing {@link java.lang.Comparable#compareTo(Object)}
 * methods.
 * 
 * It is consistent with <code>equals(Object)</code> and
 * <code>hashcode()</code> built with {@link EqualsBuilder} and
 * {@link HashCodeBuilder}.
 * </p>
 * 
 * <p>
 * Two Objects that compare equal using <code>equals(Object)</code> should
 * normally also compare equal using <code>compareTo(Object)</code>.
 * </p>
 * 
 * <p>
 * All relevant fields should be included in the calculation of the comparison.
 * Derived fields may be ignored. The same fields, in the same order, should be
 * used in both <code>compareTo(Object)</code> and <code>equals(Object)</code>.
 * </p>
 * 
 * <p>
 * To use this class write code as follows:
 * </p>
 * 
 * <pre>
 *  public class MyClass {
 *    String field1;
 *    int field2;
 *    boolean field3;
 * 
 *    ...
 * 
 *    public int compareTo(Object o) {
 *      MyClass myClass = (MyClass) o;
 *      return new CompareToBuilder()
 *        .appendSuper(super.compareTo(o)
 *        .append(this.field1, myClass.field1)
 *        .append(this.field2, myClass.field2)
 *        .append(this.field3, myClass.field3)
 *        .toComparison();
 *    }
 *  }
 * </pre>
 * 
 * @see java.lang.Comparable
 * @see java.lang.Object#equals(Object)
 * @see java.lang.Object#hashCode()
 * @see EqualsBuilder
 * @see HashCodeBuilder
 * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
 * @author Stephen Colebourne
 * @author Gary Gregory
 * @author Pete Gieser
 * @since 1.0
 * @version $Id: CompareToBuilder.java 447139 2006-09-17 20:36:53Z bayard $
 */
public class CompareToBuilder {

	/**
   * Current state of the comparison as appended fields are checked.
   */
	private int comparison;

	/**
   * <p>
   * Constructor for CompareToBuilder.
   * </p>
   * 
   * <p>
   * Starts off assuming that the objects are equal. Multiple calls are then
   * made to the various append methods, followed by a call to
   * {@link #toComparison} to get the result.
   * </p>
   */
	public CompareToBuilder() {
		super();
		comparison = 0;
	}

	// -----------------------------------------------------------------------
	/**
   * <p>
   * Appends to the <code>builder</code> the <code>compareTo(Object)</code>
   * result of the superclass.
   * </p>
   * 
   * @param superCompareTo
   *          result of calling <code>super.compareTo(Object)</code>
   * @return this - used to chain append calls
   * @since 2.0
   */
	public CompareToBuilder appendSuper(int superCompareTo) {
		if (comparison != 0) { return this; }
		comparison = superCompareTo;
		return this;
	}

	// -----------------------------------------------------------------------
	/**
   * <p>
   * Appends to the <code>builder</code> the comparison of two
   * <code>Object</code>s.
   * </p>
   * 
   * <ol>
   * <li>Check if <code>lhs == rhs</code></li>
   * <li>Check if either <code>lhs</code> or <code>rhs</code> is
   * <code>null</code>, a <code>null</code> object is less than a non-<code>null</code>
   * object</li>
   * <li>Check the object contents</li>
   * </ol>
   * 
   * <p>
   * <code>lhs</code> must either be an array or implement {@link Comparable}.
   * </p>
   * 
   * @param lhs
   *          left-hand object
   * @param rhs
   *          right-hand object
   * @return this - used to chain append calls
   * @throws ClassCastException
   *           if <code>rhs</code> is not assignment-compatible with
   *           <code>lhs</code>
   */
	public CompareToBuilder append(Object lhs, Object rhs) {
		return append(lhs, rhs, null);
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the comparison of two
   * <code>Object</code>s.
   * </p>
   * 
   * <ol>
   * <li>Check if <code>lhs == rhs</code></li>
   * <li>Check if either <code>lhs</code> or <code>rhs</code> is
   * <code>null</code>, a <code>null</code> object is less than a non-<code>null</code>
   * object</li>
   * <li>Check the object contents</li>
   * </ol>
   * 
   * <p>
   * If <code>lhs</code> is an array, array comparison methods will be used.
   * Otherwise <code>comparator</code> will be used to compare the objects. If
   * <code>comparator</code> is <code>null</code>, <code>lhs</code> must
   * implement {@link Comparable} instead.
   * </p>
   * 
   * @param lhs
   *          left-hand object
   * @param rhs
   *          right-hand object
   * @param comparator
   *          <code>Comparator</code> used to compare the objects,
   *          <code>null</code> means treat lhs as <code>Comparable</code>
   * @return this - used to chain append calls
   * @throws ClassCastException
   *           if <code>rhs</code> is not assignment-compatible with
   *           <code>lhs</code>
   * @since 2.0
   */
	public CompareToBuilder append(Object lhs, Object rhs, Comparator comparator) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.getClass().isArray()) {
			// switch on type of array, to dispatch to the correct handler
			// handles multi dimensional arrays
			// throws a ClassCastException if rhs is not the correct array type
			if (lhs instanceof long[]) {
				append((long[]) lhs, (long[]) rhs);
			} else if (lhs instanceof int[]) {
				append((int[]) lhs, (int[]) rhs);
			} else if (lhs instanceof short[]) {
				append((short[]) lhs, (short[]) rhs);
			} else if (lhs instanceof char[]) {
				append((char[]) lhs, (char[]) rhs);
			} else if (lhs instanceof byte[]) {
				append((byte[]) lhs, (byte[]) rhs);
			} else if (lhs instanceof double[]) {
				append((double[]) lhs, (double[]) rhs);
			} else if (lhs instanceof float[]) {
				append((float[]) lhs, (float[]) rhs);
			} else if (lhs instanceof boolean[]) {
				append((boolean[]) lhs, (boolean[]) rhs);
			} else {
				// not an array of primitives
				// throws a ClassCastException if rhs is not an array
				append((Object[]) lhs, (Object[]) rhs, comparator);
			}
		} else {
			// the simple case, not an array, just test the element
			if (comparator == null) {
				comparison = ((Comparable) lhs).compareTo(rhs);
			} else {
				comparison = comparator.compare(lhs, rhs);
			}
		}
		return this;
	}

	// -------------------------------------------------------------------------
	/**
   * Appends to the <code>builder</code> the comparison of two
   * <code>long</code>s.
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(long lhs, long rhs) {
		if (comparison != 0) { return this; }
		comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
		return this;
	}

	/**
   * Appends to the <code>builder</code> the comparison of two
   * <code>int</code>s.
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(int lhs, int rhs) {
		if (comparison != 0) { return this; }
		comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
		return this;
	}

	/**
   * Appends to the <code>builder</code> the comparison of two
   * <code>short</code>s.
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(short lhs, short rhs) {
		if (comparison != 0) { return this; }
		comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
		return this;
	}

	/**
   * Appends to the <code>builder</code> the comparison of two
   * <code>char</code>s.
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(char lhs, char rhs) {
		if (comparison != 0) { return this; }
		comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
		return this;
	}

	/**
   * Appends to the <code>builder</code> the comparison of two
   * <code>byte</code>s.
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(byte lhs, byte rhs) {
		if (comparison != 0) { return this; }
		comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the comparison of two
   * <code>double</code>s.
   * </p>
   * 
   * <p>
   * This handles NaNs, Infinities, and <code>-0.0</code>.
   * </p>
   * 
   * <p>
   * It is compatible with the hash code generated by
   * <code>HashCodeBuilder</code>.
   * </p>
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(double lhs, double rhs) {
		if (comparison != 0) { return this; }
		comparison = compare(lhs, rhs);
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the comparison of two
   * <code>float</code>s.
   * </p>
   * 
   * <p>
   * This handles NaNs, Infinities, and <code>-0.0</code>.
   * </p>
   * 
   * <p>
   * It is compatible with the hash code generated by
   * <code>HashCodeBuilder</code>.
   * </p>
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(float lhs, float rhs) {
		if (comparison != 0) { return this; }
		comparison = compare(lhs, rhs);
		return this;
	}

	/**
   * <p>
   * Compares two <code>doubles</code> for order.
   * </p>
   * 
   * <p>
   * This method is more comprehensive than the standard Java greater than, less
   * than and equals operators.
   * </p>
   * <ul>
   * <li>It returns <code>-1</code> if the first value is less than the
   * second.
   * <li>It returns <code>+1</code> if the first value is greater than the
   * second.
   * <li>It returns <code>0</code> if the values are equal.
   * </ul>
   * 
   * <p>
   * The ordering is as follows, largest to smallest:
   * <ul>
   * <li>NaN
   * <li>Positive infinity
   * <li>Maximum double
   * <li>Normal positive numbers
   * <li>+0.0
   * <li>-0.0
   * <li>Normal negative numbers
   * <li>Minimum double (-Double.MAX_VALUE)
   * <li>Negative infinity
   * </ul>
   * </p>
   * 
   * <p>
   * Comparing <code>NaN</code> with <code>NaN</code> will return
   * <code>0</code>.
   * </p>
   * 
   * @param lhs
   *          the first <code>double</code>
   * @param rhs
   *          the second <code>double</code>
   * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
   *         <code>0</code> if equal to rhs
   */
	public static int compare(double lhs, double rhs) {
		if (lhs < rhs) { return -1; }
		if (lhs > rhs) { return +1; }
		// Need to compare bits to handle 0.0 == -0.0 being true
		// compare should put -0.0 < +0.0
		// Two NaNs are also == for compare purposes
		// where NaN == NaN is false
		long lhsBits = Double.doubleToLongBits(lhs);
		long rhsBits = Double.doubleToLongBits(rhs);
		if (lhsBits == rhsBits) { return 0; }
		// Something exotic! A comparison to NaN or 0.0 vs -0.0
		// Fortunately NaN's long is > than everything else
		// Also negzeros bits < poszero
		// NAN: 9221120237041090560
		// MAX: 9218868437227405311
		// NEGZERO: -9223372036854775808
		if (lhsBits < rhsBits) { return -1; }
		return +1;
	}

	/**
   * <p>
   * Compares two floats for order.
   * </p>
   * 
   * <p>
   * This method is more comprehensive than the standard Java greater than, less
   * than and equals operators.
   * </p>
   * <ul>
   * <li>It returns <code>-1</code> if the first value is less than the
   * second.
   * <li>It returns <code>+1</code> if the first value is greater than the
   * second.
   * <li>It returns <code>0</code> if the values are equal.
   * </ul>
   * 
   * <p>
   * The ordering is as follows, largest to smallest:
   * <ul>
   * <li>NaN
   * <li>Positive infinity
   * <li>Maximum float
   * <li>Normal positive numbers
   * <li>+0.0
   * <li>-0.0
   * <li>Normal negative numbers
   * <li>Minimum float (-Float.MAX_VALUE)
   * <li>Negative infinity
   * </ul>
   * 
   * <p>
   * Comparing <code>NaN</code> with <code>NaN</code> will return
   * <code>0</code>.
   * </p>
   * 
   * @param lhs
   *          the first <code>float</code>
   * @param rhs
   *          the second <code>float</code>
   * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
   *         <code>0</code> if equal to rhs
   */
	public static int compare(float lhs, float rhs) {
		if (lhs < rhs) { return -1; }
		if (lhs > rhs) { return +1; }
		// Need to compare bits to handle 0.0 == -0.0 being true
		// compare should put -0.0 < +0.0
		// Two NaNs are also == for compare purposes
		// where NaN == NaN is false
		int lhsBits = Float.floatToIntBits(lhs);
		int rhsBits = Float.floatToIntBits(rhs);
		if (lhsBits == rhsBits) { return 0; }
		// Something exotic! A comparison to NaN or 0.0 vs -0.0
		// Fortunately NaN's int is > than everything else
		// Also negzeros bits < poszero
		// NAN: 2143289344
		// MAX: 2139095039
		// NEGZERO: -2147483648
		if (lhsBits < rhsBits) { return -1; }
		return +1;
	}

	/**
   * Appends to the <code>builder</code> the comparison of two
   * <code>booleans</code>s.
   * 
   * @param lhs
   *          left-hand value
   * @param rhs
   *          right-hand value
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(boolean lhs, boolean rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == false) {
			comparison = -1;
		} else {
			comparison = +1;
		}
		return this;
	}

	// -----------------------------------------------------------------------
	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>Object</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a short length array is less than a long length
   * array</li>
   * <li>Check array contents element by element using
   * {@link #append(Object, Object, Comparator)}</li>
   * </ol>
   * 
   * <p>
   * This method will also will be called for the top level of
   * multi-dimensional, ragged, and multi-typed arrays.
   * </p>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   * @throws ClassCastException
   *           if <code>rhs</code> is not assignment-compatible with
   *           <code>lhs</code>
   */
	public CompareToBuilder append(Object[] lhs, Object[] rhs) {
		return append(lhs, rhs, null);
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>Object</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a short length array is less than a long length
   * array</li>
   * <li>Check array contents element by element using
   * {@link #append(Object, Object, Comparator)}</li>
   * </ol>
   * 
   * <p>
   * This method will also will be called for the top level of
   * multi-dimensional, ragged, and multi-typed arrays.
   * </p>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @param comparator
   *          <code>Comparator</code> to use to compare the array elements,
   *          <code>null</code> means to treat <code>lhs</code> elements as
   *          <code>Comparable</code>.
   * @return this - used to chain append calls
   * @throws ClassCastException
   *           if <code>rhs</code> is not assignment-compatible with
   *           <code>lhs</code>
   * @since 2.0
   */
	public CompareToBuilder append(Object[] lhs, Object[] rhs,
			Comparator comparator) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i], comparator);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>long</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(long, long)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(long[] lhs, long[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>int</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(int, int)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(int[] lhs, int[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>short</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(short, short)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(short[] lhs, short[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>char</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(char, char)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(char[] lhs, char[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>byte</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(byte, byte)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(byte[] lhs, byte[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>double</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(double, double)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(double[] lhs, double[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>float</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(float, float)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(float[] lhs, float[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	/**
   * <p>
   * Appends to the <code>builder</code> the deep comparison of two
   * <code>boolean</code> arrays.
   * </p>
   * 
   * <ol>
   * <li>Check if arrays are the same using <code>==</code></li>
   * <li>Check if for <code>null</code>, <code>null</code> is less than
   * non-<code>null</code></li>
   * <li>Check array length, a shorter length array is less than a longer
   * length array</li>
   * <li>Check array contents element by element using
   * {@link #append(boolean, boolean)}</li>
   * </ol>
   * 
   * @param lhs
   *          left-hand array
   * @param rhs
   *          right-hand array
   * @return this - used to chain append calls
   */
	public CompareToBuilder append(boolean[] lhs, boolean[] rhs) {
		if (comparison != 0) { return this; }
		if (lhs == rhs) { return this; }
		if (lhs == null) {
			comparison = -1;
			return this;
		}
		if (rhs == null) {
			comparison = +1;
			return this;
		}
		if (lhs.length != rhs.length) {
			comparison = (lhs.length < rhs.length) ? -1 : +1;
			return this;
		}
		for (int i = 0; i < lhs.length && comparison == 0; i++) {
			append(lhs[i], rhs[i]);
		}
		return this;
	}

	// -----------------------------------------------------------------------
	/**
   * Returns a negative integer, a positive integer, or zero as the
   * <code>builder</code> has judged the "left-hand" side as less than,
   * greater than, or equal to the "right-hand" side.
   * 
   * @return final comparison result
   */
	public int toComparison() {
		return comparison;
	}

}
